package Thread;
//下面这个代码能打印hello吗？
public class ThreadDemo17 {
    public static void main(String[] args) {
        Object lock=new Object();
        Thread t=new Thread(()->{
            synchronized (lock){//真正加锁，同时把计数器+1（初始为0，+1之后就说明当前这个对象被该线程加锁一次）同时记录线程是谁
                synchronized (lock){//先判定当前加锁线程是否持有锁的线程，如果不是同一个线程，阻塞
                                    //如果是同一个线程，就只是++计数器即可，没有其他操作


                    //这段代码看起来有锁冲突，但是最终不会出现阻塞，关键在于，这两次加锁，其实是对同一个线程进行的
                    //当前由于是同一个线程，此时锁对象就知道了第二次加锁的线程，就是持有锁的线程，第二次操作，就可以直接放行通过，不会线程阻塞
                    //这个特性，称为“可重入”
                    //可重入锁就是为了防止程序员在写代码时不小心写出来双重锁的效果而使代码出现问题
                    //意思就是就算不小心写了那种双重锁代码，丰富的机制也不会让代码有问题
                    System.out.println("hello");
                }//1  把计数器-1，由于计数器不为0，不会真的解锁
            }//2---应该在2这里解锁，避免1和2之间的逻辑失去锁的保护，执行到这里，再次把计数器-1，此时计数器归零，真正解锁
            //总之就是最外层的{进行加锁，最外层的}进行解锁
        });
        t.start();
    }
}
//对于可重入锁来说，内部会持有两个信息
//1)当前这个锁是被哪个线程持有的
//加锁次数的计数器